Skip to content

0.10.1#18

Open
dzikowski wants to merge 9 commits into
mainfrom
nightly
Open

0.10.1#18
dzikowski wants to merge 9 commits into
mainfrom
nightly

Conversation

@dzikowski

Copy link
Copy Markdown
Contributor

No description provided.

dzikowski and others added 9 commits July 13, 2026 13:00
jaiph run spawns the workflow leader detached and previously stopped it
with process.kill(-pid, signal) — a POSIX-only negative-PID group kill.
On win32 that throws, the child.kill() fallback terminated only the
leader, and the agent backends / script children it spawned were
orphaned.

Add src/runtime/kernel/portability.ts exporting killProcessTree(pid,
signal) as the single sanctioned home for group kills. On POSIX it
preserves prior behavior (negative-PID group kill with a per-process
ESRCH fallback); on win32 it force-kills the whole tree with
`taskkill /pid <pid> /T /F` (spawned, not shelled) via an injectable
seam, degrading to a per-process kill if taskkill cannot launch.
Because taskkill /F is already forceful, the SIGTERM->SIGKILL
escalation is a documented no-op on win32.

Repoint every group-kill call site at the helper: run teardown
(lifecycle.ts), the prompt watchdog (prompt.ts), and the Docker
run-timeout kill (docker.ts). New unit tests stub process.platform to
cover both branches (negative-PID kill on POSIX plus ESRCH fallback;
taskkill /T argv on win32) and prove win32 never calls process.kill
with a negative PID; a src/-wide lint test asserts no production file
outside portability.ts matches `process.kill(-`. Docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Script steps previously ran by spawning the emitted file directly,
relying on the `#!/usr/bin/env <lang>` shebang and the 0o755 exec bit.
Windows honors neither, and `noexec` mounts on Linux strip the exec bit,
both breaking script execution. The runtime already knows the
interpreter since it writes the shebang itself, so `executeScript` now
reads the emitted script's shebang, resolves the interpreter through the
new `resolveInterpreterFromShebang` (`src/parse/script-bash.ts`), and
spawns `<interpreter> <scriptPath> <args...>` explicitly. The shebang
line is still written into every emitted script so they remain directly
executable by hand on POSIX, but the runtime no longer depends on it or
on the exec bit being honored. A spawn ENOENT from a missing interpreter
now surfaces as a diagnosable Jaiph error naming the interpreter instead
of a raw `spawn <name> ENOENT`. New unit tests assert the resolved
interpreter and argv on an injectable `_scriptSpawn` seam, prove a script
with the exec bit stripped (0o644) still runs on POSIX, and prove a
missing-interpreter shebang produces the diagnosable error.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Inline workflow shell lines (executeShLine) and CLI hook commands used a
hardcoded spawn("sh", ["-c", ...]), which fails on win32 where there is no
sh on the default PATH. Add resolveShell() to the portability module as the
single seam both call sites go through: on POSIX it returns bare sh; on
win32 it locates Git for Windows' bundled sh.exe, first on PATH and then in
the standard install layouts (<Git>/bin/sh.exe, <Git>/usr/bin/sh.exe) under
each known root, throwing a diagnosable E_NO_POSIX_SHELL error naming Git
for Windows if none is found. Resolution is memoized per process. Inline
lines are never translated to cmd/PowerShell, so POSIX shell semantics are
unchanged. Unit tests stub process.platform and the PATH/existence lookup
across all branches, and a src/-wide lint test asserts no spawn("sh") call
site remains outside portability.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Close three remaining POSIX assumptions that broke a host-only Windows
runtime. prepareClaudeEnv now falls back to os.homedir() when neither
execEnv.HOME nor process.env.HOME is set, so USERPROFILE-only
environments resolve the .claude config dir; an explicit execEnv.HOME
still wins. resolveDockerConfig forces host-only mode on win32 with a
one-line notice (same UX as JAIPH_UNSAFE=true), so the CLI never probes
docker and never hard-fails on a missing daemon, and
JAIPH_DOCKER_ENABLED=true cannot override it. A new canUseAnsi() helper
in the portability module centralizes the isTTY + NO_COLOR gate; every
color/erase emission site routes through it so the policy lives in one
place. Adds unit tests for each and a src-wide lint test asserting no
production file outside portability.ts gates directly on isTTY &&
NO_COLOR. Docs updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add a Windows x64 target to the release workflow so every release ships
a fifth standalone binary alongside darwin/linux x arm64/x64. A new
bun-windows-x64 matrix entry (with an ext field so the compiled outfile
and uploaded artifact carry the .exe suffix) produces jaiph-windows-x64.exe;
Bun has no windows-arm64 target so Windows is x64 only. The .exe is
included in SHA256SUMS generation and in both the stable and nightly
gh release upload lists.

A new sanity-windows job runs on windows-latest, downloads the .exe
artifact, and runs jaiph-windows-x64.exe --version through a version
gate; the publish job now needs [build, sanity-windows], so a Windows
version mismatch fails the whole release. The linux-x64 gate's inline
comparison is extracted into a shared, testable
scripts/release-version-check.sh that both gates delegate to.

Update the release asset naming contract in docs/contributing.md and
docs/architecture.md, and add integration/release-workflow.test.ts
asserting the five-binary matrix, SHA256SUMS and upload-list coverage,
the shared gate behavior, and naming-contract/installer parity.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add docs/install.ps1 as the Windows counterpart to the POSIX docs/install
(run with irm https://jaiph.org/install.ps1 | iex). It downloads
jaiph-windows-x64.exe and SHA256SUMS from the pinned release ref (default
the current stable tag, overridable via JAIPH_REPO_REF / first arg plus
JAIPH_RELEASE_BASE_URL for local file:// dirs used by tests), verifies the
SHA-256 with Get-FileHash and installs nothing on mismatch, then installs
to %LOCALAPPDATA%\jaiph\bin\jaiph.exe (overridable via JAIPH_BIN_DIR), adds
it to the user PATH if absent, and prints the same try-it hints as the bash
installer. Non-x64 / ARM Windows exits non-zero with a documented
unsupported-platform message.

The bash installer now rejects Windows-like uname values and points at the
PowerShell one-liner, and prepare_release.jh rewrites the pinned ref in both
installers in lockstep. CI gains an installer-powershell job on
windows-latest that cross-compiles the real .exe and runs
e2e/tests/installer_powershell.ps1 (checksum mismatch, unsupported arch,
happy-path install with no Node/npm/Bun on PATH); the Docker publish job now
needs it. Host-portable guards live in integration/installer-powershell.test.ts.
Docs updated (setup.md, index.html, architecture.md, contributing.md, README).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The landing page hero install card now offers a Windows PowerShell path
alongside the POSIX curl | bash one-liners. A new .os-switch sub-toggle
(macOS/Linux vs Windows) sits above the run-sample / init-project /
just-install tabs, and each panel wraps its content in .os-variant blocks.

On load, attachOsSwitch() (docs/assets/js/main.js) auto-selects the
Windows variant for Windows visitors via isWindowsPlatform(), which
prefers navigator.userAgentData?.platform and falls back to
navigator.platform. macOS/Linux visitors keep today's POSIX default with
no layout shift; manual switching stays available and is remembered
card-wide. The 'Just install' Windows variant exposes the copy-able
irm https://jaiph.org/install.ps1 | iex line; the run-sample and
init-project tabs (no PowerShell pipe equivalent) show the install
one-liner plus a short 'then run:' jaiph command instead of a bash-only
default. The static-render constraint holds: the POSIX variant carries
is-active in the markup and CSS hides inactive variants, so with JS
disabled all bash one-liners render and no panel is blank.

New Playwright cases in the docs suite assert the Windows default, the
unchanged macOS/Linux default, manual platform + tab switching, the
clipboard contents of the Windows copy button, and the JS-disabled
static render.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant